'use strict';

const db = uniCloud.database();
const businessInfoDBName = 'zhy_business_info';
const orderProfitSharingDBName = 'zhy_order_profitsharing';
const orderDBName = 'zhy_order';
const business_bind_receiverDBName = 'zhy_business_bind_receiver';
//云函数暂时不支持import写法，只能用require导入
const AlipaySdk = require('alipay-sdk').default;
//node内置的模块
const fs = require('fs');
const path = require('path');
const notifyUrl = 'https://fc-mp-4ef38036-8cda-4b90-b1a1-b03b064f2485.next.bspapp.com/openapi/pay/zhy-pay-notify'

const alipaySdk = new AlipaySdk({
	appId: '2019111369110790',
	signType: 'RSA2',
	privateKey: fs.readFileSync(__dirname + '/cert/app_private_key.pem', 'UTF-8'),
	alipayRootCertPath: path.join(__dirname, './cert/alipayRootCert.crt'),
	appCertPath: path.join(__dirname, './cert/appCertPublicKey.crt'),
	alipayPublicCertPath: path.join(__dirname, './cert/alipayCertPublicKey_RSA2.crt'),
	// gateway: 'https://openai.alipay.com/gateway.do'
});

exports.main = async (event, context) => {
	//event为客户端上传的参数
	console.log('event : ', event)
	if (event.type == 1) {
		/* event示例
		{code:'xxxxxxxxx'}
		*/
		return getOpenid(event.code)
	} else if (event.type == 2) {
		/* event示例
		{
			orderId: orderId,
			openid: uni.getStorageSync(app.globalData.session.userKey),
			amount: price,
			amountFen: this.$mytools.regYuanToFen(price, 100),
			title: '商户充值',
			type: 2, //统一下单--直连支付模式，如：商户充值--下单
			remark: '备注:商户充值',
		}
		*/
		// 统一下单
		return unifiedorder(event, context)
	} else if (event.type == 3) {
		/*
		{
			// user用户 tx提现
			out_batch_no: this.$idGenerator.createUniqueId('usertx'),
			batch_name: '用户提现',
			batch_remark: '感谢参与霸王补贴',
			total_amount: total_amount, //单位：分
			total_num: 1,
			transfer_detail_list: [{
				out_detail_no: this.$idGenerator.createUniqueId('usertx'),
				transfer_amount: total_amount,
				transfer_remark: this.$mytools.formatTimestampToDateStr(new Date().getTime()) +
					'日一次性提现',
				openid: uni.getStorageSync(app.globalData.session.userKey),
				user_name: null //>2000元才必须
			}]
		}
		*/
		// 用户提现:单次转账到用户
		return userWithdrawal(event, context)
	} else if (event.type == 4) {
		/*
		{
			orderId: orderId,
			openid: uni.getStorageSync(app.globalData.session.userKey),
			amount: price,
			amountFen: this.$mytools.regYuanToFen(price, 100),
			title: '商户充值',
			type: 4, //服务商支付模式--下单
			remark: '备注:商户充值',
		}
		*/
		// 统一下单:分账，聚合支付下单，开启分账
		return partnerUnifiedorder(event, context)
	} else if (event.type == 5) {
		/*
		{
			description: profitSharingParam.description, // 分账描述
			amountFen: params.amountFen, // 分账金额，单位：分
			orderId: profitSharingParam.orderId, // 商户分账单号，并非商户的订单号，分账单号=ps+orderId
			offlineBusinessId: profitSharingParam.offlineBusinessId // 商户id
		}
		*/
		// 发起分账请求
		return partnerProfitSharing(event, context)
	} else if (event.type == 6) {
		/*
		{
			offlineBusinessId: businessId
		}
		*/
		// 添加分账接收方。分帐前比做！
		return profitsharingaddreceiver(event, context)
	}
	console.log('类型不规范');
	return '';;
};

// 获取openid
async function getOpenid(code) {
	console.log(__dirname + '/cert/app_private_key.pem');
	const result = await alipaySdk.exec('alipay.system.oauth.token', {
		grantType: 'authorization_code',
		code: code,
		// refreshToken: 'token'
	});
	console.log(JSON.stringify(result));
	return result.openId;
}

// 统一下单：不分账。用户直接到自己
async function unifiedorder(event, context) {
	const result = await alipaySdk.exec('alipay.trade.create', {
		notifyUrl: notifyUrl,
		bizContent: {
			out_trade_no: event.orderId,
			total_amount: event.amount, //单位:元。精确到小数点后两位
			buyer_open_id: event.openid,
			subject: event.title
		}
	}).catch(error => {
		return error
	});
	//返回tradeNo、outTradeNo
	/*
	{
	    "code": "10000",
	    "msg": "Success",
	    "outTradeNo": "bs22024060610544974459",
	    "tradeNo": "2024060622001452921428541694",
	    "traceId": "0b2282f117176424899565699e07ee"
	}
	*/
	console.log(JSON.stringify(result));
	// 保存订单
	if (result.code != null && result.code.toString() === "10000") {
		// success
		console.log('下单成功');
		// 保存订单
		event.pay_success_status = 1
		event.amount = event.amountFen
		event.remark = event.remark
		event.status = 0
		event.clientIP = context.CLIENTIP
		event.trade_type = 'JSAPI' // 和微信一致，表示小程序支付
		event.order_time = parseInt(new Date().getTime() / 1000) // 支付宝返回值没有时间戳
		event.pay_time = null
		event.pay_success_status = 1
		event.profit_sharing = 0
		event.trade_no = result.trade_no // 支付宝交易号：【示例值】2015042321001004720200028594.支付宝系统的订单号下单后就直接就返回了
		saveOrder(event)
		return result;
	} else {
		// 下单失败
		event.pay_success_status = 1
		event.amount = event.amountFen
		event.remark = event.remark
		event.status = 0
		event.clientIP = context.CLIENTIP
		event.trade_type = 'JSAPI'
		event.order_time = parseInt(new Date().getTime() / 1000)
		event.pay_time = null
		event.pay_success_status = 0
		event.pay_fail_reason = toString(JSON.parse(result.error).message)
		event.profit_sharing = 0
		saveOrder(event)
		return null
	}
}

// 保存订单到zhy_order
function saveOrder(order) {
	if (order == null || order == undefined || order == '' || JSON.stringify(order) == '{}') {
		return {
			errSubject: 'order_param_lack',
			errCode: 0,
			errMsg: '订单信息不全'
		}
	}
	let trade_no = order.trade_no
	if (trade_no == undefined || trade_no == null || trade_no == '') {
		trade_no = ''
	}
	let orderInfo = {
		// add
		operateType: 1,
		// 字段
		openid: order.openid,
		orderId: order.orderId,
		title: order.title,
		amount: order.amountFen,
		type: order.type,
		trade_type: order.trade_type,
		remark: order.remark,
		order_time: order.order_time,
		pay_time: order.pay_time,
		status: order.status,
		clientIP: order.clientIP,
		pay_success_status: order.pay_success_status,
		order_plat: 'mp-alipay',
		profit_sharing: order.profit_sharing,
		order_fail_reason: order.order_fail_reason,
		pay_fail_reason: order.pay_fail_reason,
		trade_no: trade_no,
	}
	uniCloud.callFunction({
		name: 'zhy-order',
		data: orderInfo
	})
}

// 普通用户：提现到零钱-支付宝叫做转账给用户(单笔转账接口)
async function userWithdrawal(event, context) {
	const result = await alipaySdk.exec('alipay.fund.trans.uni.transfer', {
		// notifyUrl: 'https://wwwaass',
		bizContent: {
			out_biz_no: event.out_batch_no,
			trans_amount: event.total_amount, // 单位:元
			biz_scene: 'DIRECT_TRANSFER', //业务场景。单笔无密转账固定为DIRECT_TRANSFER
			product_code: 'TRANS_ACCOUNT_NO_PWD', //销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
			order_title: event.batch_name,
			payee_info: {
				identity: event.transfer_detail_list[0].openid,
				identity_type: 'ALIPAY_OPEN_ID',
				// name: ''
			},
			remark: event.batch_remark,
			// business_params: ''
		}
	}).catch(error => {
		return error
	});
	console.log(JSON.stringify(result));
	return result
}

//========================================分账相关=========================================//
// 支付宝支付分账步骤：https://opendocs.alipay.com/open/direct-payment/ufs0lb
/*
1.绑定分账关系（alipay.trade.royalty.relation.bind） 
2.收单结算  
3.分账剩余金额查询 
4.分账 
5.分账解冻
*/
// 统一下单：分账
async function partnerUnifiedorder(event, context) {
	const params = {
		notifyUrl: notifyUrl,
		bizContent: {
			out_trade_no: event.orderId,
			total_amount: event.amount, //单位:元。精确到小数点后两位
			buyer_open_id: event.openid,
			subject: event.title,
			extend_params: {
				royalty_freeze: true //【描述】是否进行资金冻结，用于后续分账，true表示资金冻结，false或不传表示资金不冻结
			}
		}
	}
	console.log(params);
	// const result = await pay.transactions_jsapi(params);
	const result = await alipaySdk.exec('alipay.trade.create', params).catch(error => {
		return error
	});
	//返回tradeNo、outTradeNo
	/*
	{
	    "code": "10000",
	    "msg": "Success",
	    "outTradeNo": "bs22024060610544974459",
	    "tradeNo": "2024060622001452921428541694",
	    "traceId": "0b2282f117176424899565699e07ee"
	}
	*/
	console.log(JSON.stringify(result));
	if (result != null && result.status == 200) {
		// success
		console.log('下单成功');
		/*
		#   {
		#     appId: 'appid',
		#     timeStamp: '1609918952',
		#     nonceStr: 'y8aw9vrmx8c',
		#     package: 'prepay_id=wx0615423208772665709493edbb4b330000',
		#     signType: 'RSA',
		#     paySign: 'JnFXsT4VNzlcamtmgOHhziw7JqdnUS9qJ5W6vmAluk3Q2nska7rxYB4hvcl0BTFAB1PBEnHEhCsUbs5zKPEig=='
		#   }
		*/
		// 保存订单
		event.pay_success_status = 1
		event.amount = event.amountFen
		event.remark = event.remark
		event.status = 0
		event.clientIP = context.CLIENTIP
		event.trade_type = 'JSAPI'
		event.order_time = result.data.timeStamp
		event.pay_time = null
		event.pay_success_status = 1
		event.profit_sharing = 1
		event.trade_no = result.trade_no
		saveOrder(event)
		return result.data;
	} else {
		// 下单失败
		event.pay_success_status = 1
		event.amount = event.amountFen
		event.remark = event.remark
		event.status = 0
		event.clientIP = context.CLIENTIP
		event.trade_type = 'JSAPI'
		event.order_time = parseInt(new Date().getTime() / 1000)
		event.pay_time = null
		event.pay_success_status = 0
		event.pay_fail_reason = toString(JSON.parse(result.error).message)
		event.profit_sharing = 1
		saveOrder(event)
		return null
	}
}

// 收单结算+发起分账请求(支付成功后调用)
// ：alipay.trade.settle.confirm + alipay.trade.order.settle  .out_order_no/out_request_no生成格式：ps+商户订单号(orderId)
async function partnerProfitSharing(event, context) {
	let businessId = event.offlineBusinessId
	// 查询出business信息
	let businessInfo = await getBusinessInfo(businessId)
	if (businessInfo == null) {
		console.log('无此商户：' + businessId);
		return null
	} else {
		if (businessInfo.addAlipayPayReceiverSuccess === 0) {
			await profitsharingaddreceiver({
				offlineBusinessId: businessId
			})
		}
	}
	// businessInfo
	console.log(context.CLIENTIP);
	// 根据orderId查询trade_no(支付宝订单号)
	let tradeNo = getTradeNoByOrderId(event.orderId)
	let confirm_out_request_no = 'confirm' + event.orderId
	let yuan = regFenToYuan(event.amountFen)
	let confimParam = {
		out_request_no: confirm_out_request_no, // 确认结算请求流水号，开发者自行生成并保证唯一性，作为业务幂等性控制
		trade_no: tradeNo, // 
		settle_info: {
			settle_detail_infos: [{
				trans_in_type: 'userId',
				trans_in: businessInfo.bs_alipay_no, //以2088开头的纯16位数字
				amount: yuan, //结算的金额，单位为元。在创建订单和支付接口时必须和交易金额相同。
			}]
		},
		extend_params: {
			royalty_freeze: true
		}
	}
	let confirmResult = await alipaySdk.exec('alipay.trade.settle.confirm', confimParam);
	console.log(JSON.stringify(confirmResult));
	if (confirmResult != null && confirmResult.code === '10000') {
		// success
		console.log('收单结算成功');
		saveProfitSharingOrder(confimParam, confirmResult, 1, 1)
		// 请求分账，并分账完毕后解冻
		let settle_out_request_no = 'settle' + event.orderId
		let profitSharingRaram = {
			out_request_no: settle_out_request_no,
			trade_no: tradeNo,
			royalty_parameters: {
				royalty_type: 'transfer',
				trans_in_type: 'userId',
				trans_in: businessInfo.bs_alipay_no,
				amount: yuan, //分账的金额，单位为元
				desc: '分账', //分账描述
			},
			extend_params: {
				// 【描述】"冻结分账场景下生效，其他场景传入无效。代表该交易分账是否完结，可选值：true/false，
				// 不传默认为false。true：代表分账完结，则本次分账处理完成后会把该笔交易的剩余冻结金额全额解冻。false：代表分账未完结。"
				royalty_finish: true
			},
			// 分账模式，目前有两种分账同步执行sync，分账异步执行async，不传默认同步执行
			royalty_mode: 'sync'
		}
		let profitsharingResult = await alipaySdk.exec('alipay.trade.order.settle', profitSharingRaram);
		// 保存分帐前确认清单
		console.log('分账请求结果');
		console.log(JSON.stringify(profitsharingResult));
		/*
		 {
		        "code": "10000",
		        "msg": "Success",
		        "trade_no": "2015070921001004130000127422",
		        "settle_no": "20210718002530070036530006474222" //支付宝分账单号，可以根据该单号查询单次分账请求执行结果
		    }
		*/
		if (profitsharingResult != null && profitsharingResult.code === '10000') {
			// 分账请求成功
			saveProfitSharingOrder(profitSharingRaram, profitsharingResult, 1, 2)
		} else {
			// 分账确认清单请求失败
			saveProfitSharingOrder(profitSharingRaram, profitsharingResult, 0, 2)
		}
		return profitsharingResult;
	} else {
		// 失败
		saveProfitSharingOrder(confimParam, confirmResult, 0, 1)
		return null
	}
}

// 添加分账接收方。商户入驻成功后添加接收方(步骤1)
async function profitsharingaddreceiver(event, context) {
	let businessId = event.offlineBusinessId
	// 查询出business信息
	let businessInfo = await getBusinessInfo(businessId)
	if (businessInfo == null) {
		console.log('无此商户：' + businessId);
		return null
	} else {
		if (businessInfo.addAlipayPayReceiverSuccess === 1) {
			// 已经成功添加收款方
			console.log(businessId + '已添加分账接收方，无需再次添加');
			return null
		}
	}
	let bindParams = {
		receiver_list: [{
			// 分账接收方真实姓名。 绑定分账关系时： 当分账方类型是userId时，本参数可以不传，若上传则进行校验不上传不会校验。 当分账方类型是loginName时，本参数必传。
			// name: '',
			type: 'userId', // userId,openId,loginName
			account: businessInfo.bs_alipay_no, //userId 支付宝商户号：2088开头
			// account_open_id: businessInfo.create_alipay_openid, // 和account 2选1
			memo: '分账给商户',
		}],
		out_request_no: 'zhybsbind' + generateId()
	}
	const result = await alipaySdk.exec('alipay.trade.royalty.relation.bind', bindParams);
	console.log('添加分账接收方结果');
	console.log(JSON.stringify(res));
	// 保存入库：1.zhy_business_bind_receiver 2.保存到商户表，标识是否成功即可
	if (res.code === '10000') {
		//成功
		console.log('成功');
		db.collection(dbCollectionName).doc(businessInfo._id).update({
			addAlipayPayReceiverSuccess: 1
		});
		saveBindRecieverRecord(bindParams, res, 1)
	} else {
		console.log('失败 ');
		db.collection(dbCollectionName).doc(businessInfo._id).update({
			addAlipayPayReceiverSuccess: 0,
			addAlipayReceiverFailReason: res.sub_msg
		});
		saveBindRecieverRecord(bindParams, res, 0)
	}
	return res
}

// 获取商户详情
async function getBusinessInfo(businessId) {
	if (businessId == undefined || businessId == '' || businessId == '') {
		return null
	}
	let bs = await db.collection(businessInfoDBName).where({
		offlineBusinessId: businessId
	}).limit(1).get()
	if (bs.data == null || bs.data.length == 0) {
		return null
	}
	return bs.data[0]
}

// 保存分账结果
function saveProfitSharingOrder(inputParam, outputParam, success, confirm) {
	let p = {
		profitsharing_type: 2, //分账平台类型： 1微信 2支付宝
		input_param: inputParam,
		output_param: outputParam,
		success: success,
		ps_time: new Date().getTime(),
		profitsharing_id: inputParam.out_request_no,
		alipay_confirm: confirm
	}
	db.collection(orderProfitSharingDBName).add(p)
}

// 保存添加分账账户输入和结果
async function saveBindRecieverRecord(intput, output, sucess) {
	db.collection(business_bind_receiverDBName).add({
		bindType: 1,
		input_param: intput,
		output_param: output,
		success: success,
		addTime: parseInt(new Date().getTime() / 1000)
	})
}

// 生成时间戳id
function generateId() {
	let uniqueId = Math.random().toString(36).substr(5, 9) + new Date().getTime().toString()
	return uniqueId
}

//金额分=>元
function regFenToYuan(fen) {
	var num = fen;
	num = fen * 0.01;
	num += '';
	var reg = num.indexOf('.') > -1 ? /(\d{1,3})(?=(?:\d{3})+\.)/g : /(\d{1,3})(?=(?:\d{3})+$)/g;
	num = num.replace(reg, '$1');
	num = toDecimal2(num)
	return num
};
//========================================分账相关=========================================//